use e_utils::cmd::Cmd;
use std::ptr;
use std::ptr::null_mut;
use winapi::shared::minwindef::{DWORD, HKEY};
use winapi::shared::winerror::{ERROR_NO_MORE_ITEMS, ERROR_SUCCESS, S_OK};
use winapi::um::shellapi::{
  SHEmptyRecycleBinW, SHERB_NOCONFIRMATION, SHERB_NOPROGRESSUI, SHERB_NOSOUND,
};
use winapi::um::winnt::{KEY_ENUMERATE_SUB_KEYS, KEY_SET_VALUE};
use winapi::um::winreg::{
  RegCloseKey, RegDeleteKeyW, RegDeleteValueW, RegEnumValueW, RegOpenKeyExW, HKEY_CURRENT_USER,
  LSTATUS,
};

use crate::share::{get_powershell_path, SYSTEM_WIN32};
use std::env;
use std::ffi::OsString;
use std::fs;
use std::os::windows::ffi::OsStrExt;
use std::path::PathBuf;

fn add_log(message: &str, level: &str) {
  println!("[{}] {}", level, message);
}

/// 清理回收站
pub fn empty_recycle_bin() -> e_utils::AnyResult<String> {
  // 调用SHEmptyRecycleBinW函数来清理回收站
  let result = unsafe {
    SHEmptyRecycleBinW(
      ptr::null_mut(),
      ptr::null(),
      SHERB_NOCONFIRMATION | SHERB_NOPROGRESSUI | SHERB_NOSOUND,
    )
  };
  if result == S_OK || result == 0x8000ffffu32 as i32 {
    Ok("Recycle cleared！ PASS".to_string())
  } else {
    Err(format!("Error while clearing the Recycle Bin:{:x}", result).into())
  }
}

/// 清理最近访问
pub fn empty_access_log() -> e_utils::AnyResult<String> {
  let appdata = env::var("APPDATA")?;
  let recent_folder = PathBuf::from(&appdata).join("Microsoft\\Windows\\Recent");
  let automatic_destinations = recent_folder.join("AutomaticDestinations");
  let custom_destinations = recent_folder.join("CustomDestinations");

  // Remove files in the Recent folder
  if let Ok(entries) = fs::read_dir(&recent_folder) {
    for entry in entries {
      if let Ok(entry) = entry {
        if let Ok(metadata) = entry.metadata() {
          if metadata.is_file() {
            let _ = fs::remove_file(entry.path());
          }
        }
      }
    }
  }

  // Remove the AutomaticDestinations folder
  if automatic_destinations.exists() {
    let _ = fs::remove_dir_all(&automatic_destinations);
  }

  // Remove the CustomDestinations folder
  if custom_destinations.exists() {
    let _ = fs::remove_dir_all(&custom_destinations);
  }

  add_log("Quick Access history cleared successfully.", "info");

  let keys = [
    "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Start_TrackProgs",
    "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Start_TrackDocs",
  ];

  for key_path in &keys {
    let key_path: Vec<u16> = key_path.encode_utf16().chain(Some(0)).collect();
    let mut key: HKEY = null_mut();

    let result: LSTATUS = unsafe {
      RegOpenKeyExW(
        winapi::um::winreg::HKEY_CURRENT_USER,
        key_path.as_ptr(),
        0,
        KEY_SET_VALUE | KEY_ENUMERATE_SUB_KEYS,
        &mut key,
      )
    };

    if result == ERROR_SUCCESS as LSTATUS {
      let delete_result: LSTATUS = unsafe {
        RegDeleteKeyW(
          key,
          "Recent\0".encode_utf16().collect::<Vec<u16>>().as_ptr(),
        )
      };

      if delete_result == ERROR_SUCCESS as LSTATUS {
        add_log(
          &format!(
            "Quick Access history in {} cleared successfully.",
            String::from_utf16_lossy(&key_path)
          ),
          "info",
        );
      } else {
        add_log(
          &format!(
            "Error clearing Quick Access history in {}: {}",
            String::from_utf16_lossy(&key_path),
            delete_result
          ),
          "info",
        );
      }

      unsafe {
        RegCloseKey(key);
      }
    } else {
      add_log(
        &format!(
          "Error opening registry key {}: {}",
          String::from_utf16_lossy(&key_path),
          result
        ),
        "info",
      );
    }
  }
  Ok("EMPTY ACCESS_LOG PASS".to_string())
}

/// 清空活动访问历史
pub fn empty_activity_history() -> e_utils::AnyResult<String> {
  Cmd::new("powershell.exe")
    .args([
      "-Command",
      "Get-History | ForEach-Object { Remove-History $_.Id }",
    ])
    .cwd(get_powershell_path())
    .output()?;
  Ok("EMPTY ACTIVITY HISTORY PASS".to_string())
}

/// Convert a Rust string to a null-terminated UTF-16 encoded string suitable for use with WinAPI.
fn to_utf16_null_terminated(s: &str) -> Vec<u16> {
  OsString::from(s).encode_wide().chain(Some(0)).collect()
}

/// 清空运行记录
pub fn empty_run_history() -> e_utils::AnyResult<String> {
  let path = to_utf16_null_terminated(r"Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU");

  // Open the registry key
  let mut hkey: winapi::shared::minwindef::HKEY = null_mut();
  let result = unsafe {
    RegOpenKeyExW(
      HKEY_CURRENT_USER,
      path.as_ptr(),
      0,
      KEY_SET_VALUE | KEY_ENUMERATE_SUB_KEYS,
      &mut hkey,
    )
  };

  if result != ERROR_SUCCESS as i32 {
    unsafe { RegCloseKey(hkey) };
    return Err(format!("Failed to open registry key: {}", result).into());
  }

  // Enumerate and delete each value in the subkey
  let mut index: DWORD = 0;
  let mut value_name: [u16; 16383] = [0; 16383]; // Buffer size for value name
  loop {
    let mut value_name_size: DWORD = value_name.len() as DWORD;
    let mut value_type: DWORD = 0;
    let mut value_data: [u8; 1024] = [0; 1024]; // Buffer size for value data
    let mut value_data_size: DWORD = value_data.len() as DWORD;

    let enum_result = unsafe {
      RegEnumValueW(
        hkey,
        index,
        value_name.as_mut_ptr(),
        &mut value_name_size,
        null_mut(),
        &mut value_type,
        value_data.as_mut_ptr(),
        &mut value_data_size,
      )
    };

    if enum_result == ERROR_NO_MORE_ITEMS as i32 {
      break; // No more items to enumerate
    } else if enum_result != ERROR_SUCCESS as i32 {
      unsafe { RegCloseKey(hkey) };
      return Err(format!("Failed to enumerate registry values: {}", enum_result).into());
    }

    // Delete the value
    let delete_result = unsafe { RegDeleteValueW(hkey, value_name.as_ptr()) };

    if delete_result != ERROR_SUCCESS as i32 {
      unsafe { RegCloseKey(hkey) };
      return Err(format!("Failed to delete registry value: {}", delete_result).into());
    }

    index += 1;
  }

  unsafe { RegCloseKey(hkey) };

  Ok("EMPTY RUN_HISTORY PASS".to_string())
}

/// 清空网络共享
pub fn empty_netshare(name: &str) -> e_utils::AnyResult<String> {
  let mut name = name;
  if name == "" {
    name = "*";
  }
  Cmd::new("net")
    .args(["use", name, "/DELETE", "/YES"])
    .cwd(SYSTEM_WIN32)
    .output()?;
  Ok("EMPTY NETSHARE PASS".to_string())
}
